﻿using ArielCore.MixedDataBase.MySql;
using FluentAssertions;
using Masuit.Tools;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NewRetail.Application.Components.Goods.Entity;
using NewRetail.Application.Components.Goods.Model;
using NewRetail.Application.Components.Platform.Entity;
using NewRetail.Application.Components.Warehouse.Entity;
using NewRetail.Application.Core;
using NewRetail.Application.Core.Entity;
using NewRetail.Application.Core.SingleStore;
using NewRetail.Application.DataAccess;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using Org.BouncyCastle.Crypto;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

namespace NewRetail.Application.Components.Goods
{
    public class GetWarehouseGoodsDto : EntityDto
    {
        public DateTime? UpdateTime { get; set; }
        public string WarehouseNo { get; set; }

        public int? Page { get; set; }
    }

    public class GetWarehouseMemberDto : EntityDto
    {
        public DateTime? UpdateTime { get; set; }
        public string WarehouseNo { get; set; }

        public int? Page { get; set; }
    }

    public interface IGoodsInfoService : IApplicationService
    {
        Task<GoodsInfo[]> AttachGoodsPrice(GoodsInfo[] data, string warehouseIds = "");
        Task<GoodsInfo[]> AttachInOutWarehousing(GoodsInfo[] data, string warehouseIds = "");
        /// <summary>
        /// 关联商品分类
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        Task<GoodsInfo[]> AttachGoodsCategory(GoodsInfo[] data);
        /// <summary>
        /// 综合报表添加额外数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        Task<GoodsComprehensiveDto[]> AttachGoodsExtInfo(GoodsInfo[] data);
        /// <summary>
        /// 手机掌售通商品展示添加额外数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        Task<GoodsMobileComprehensiveDto[]> AttachGoodsMobileExtInfo(GoodsInfo[] data);
        /// <summary>
        /// 手机掌售通商品展示添加额外数据，根据商品Id获取的
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        Task<GoodsMobileDetDto[]> AttachGoodsMobileExtInfoByIds(GoodsInfo[] data);
        /// <summary>
        /// 手机掌售通商品综合查询添加额外数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        Task<GoodsMobileComprehensiveDto[]> AttachGoodsMobileComprehensiveExtInfo(GoodsInfo[] data);
        /// <summary>
        /// 商品综合查询数据导出
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        Task<Stream> ExportComprehensiveGoodsInfo(GoodsComprehensiveDto[] data);
        /// <summary>
        /// 颜色尺码综合报表查询
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        Task<GoodsTsInfoDto[]> GetGoodsTsInfo(ProductPagingColorSizeRequestDto inputDto);
        /// <summary>
        /// 更新是否新品的状态
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        Task UpdateIsNewProductStatus(UpdateGoodsIsNewProductStatusDto[] dto);
        /// <summary>
        /// 下拉列表查询商品，通过查询语句
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        Task<IEnumerable<QueryAllGoodsByWarehouseResponse>> QueryAllGoodsByWarehouseBySql(QueryAllGoodsByWarehouseInputDto dto);
    }

    public class GoodsInfoService : ApplicationService, IGoodsInfoService
    {
        private readonly IRepository<GoodsInfo> goodsInfos;
        private readonly ISingleStoreService singleStoreService;
        private readonly ILogger logger;
        private readonly IEntityHelper entityHelper;

        private readonly IMsSqlDbRepository<NewRetailDapperDbContext> _dapperRepository;

        public GoodsInfoService(IRepository<GoodsInfo> goodsInfos, ISingleStoreService singleStoreService, ILogger<GoodsInfoService> logger, IEntityHelper entityHelper,
            IMsSqlDbRepository<NewRetailDapperDbContext> dapperRepository)
        {
            this.goodsInfos = goodsInfos;
            this.singleStoreService = singleStoreService;
            this.logger = logger;
            this.entityHelper = entityHelper;
            _dapperRepository = dapperRepository;
        }

        async Task<WarehouseGoods[]> QueryGoodsPriceByIds(IEnumerable<string> ids)
        {
            var db = await this.goodsInfos.GetDbContextAsync();

            var prices = await db.Set<WarehouseGoods>().Where(x => ids.Contains(x.goodsID)).ToArrayAsync();

            var warehouse = await db.Set<NewRetail.Application.Components.Warehouse.Entity.Warehouse>().Where(x => prices.Select(x => x.warehouseID).Contains(x.Id)).ToArrayAsync();
            //添加供应商 add by cl 20221204
            var inOutWarehouses = await db.Set<InOutWarehousing>().Where(x => prices.Select(x => x.goodsID).Contains(x.goodsID)).ToArrayAsync();
            var suppliers = await db.Set<Supplier>().ToArrayAsync();
            //添加会员价
            var goodsMemberPrices = await db.Set<GoodsMemberPrice>().Where(x => ids.Contains(x.goodsID)).ToArrayAsync();

            foreach (var m in prices)
            {
                m.Warehouse = warehouse.FirstOrDefault(x => x.Id == m.warehouseID);
                m.Supplier = suppliers.FirstOrDefault(x => x.Id == inOutWarehouses.FirstOrDefault(y => y.goodsID == m.goodsID)?.supplierID);
                m.GoodsMemberPrice = goodsMemberPrices.FirstOrDefault(x => x.goodsID == m.goodsID && x.warehouseID == m.warehouseID);
            }

            return prices;
        }
        /// <summary>
        /// 查询出会员价
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        async Task<GoodsMemberPrice[]> QueryGoodsMemberPriceByIds(IEnumerable<string> ids)
        {
            var db = await this.goodsInfos.GetDbContextAsync();

            var prices = await db.Set<GoodsMemberPrice>().Where(x => ids.Contains(x.goodsID)).ToArrayAsync();

            var warehouse = await db.Set<NewRetail.Application.Components.Warehouse.Entity.Warehouse>().Where(x => prices.Select(x => x.warehouseID).Contains(x.Id)).ToArrayAsync();
            
            foreach (var m in prices)
            {
                m.Warehouse = warehouse.FirstOrDefault(x => x.Id == m.warehouseID);
            }

            return prices;
        }

        /// <summary>
        /// 查询商品对应的进货单
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        async Task<InOutWarehousing[]> QueryInOutWarehousingsByIds(IEnumerable<string> ids)
        {
            var db = await this.goodsInfos.GetDbContextAsync();

            var inOutWarehousings = await db.Set<InOutWarehousing>().Where(x => ids.Contains(x.goodsID) && x.inOrOut == 1).ToArrayAsync();

            return inOutWarehousings;
        }

        public async Task<GoodsInfo[]> AttachGoodsPrice(GoodsInfo[] data, string warehouseIdParam = "")
        {
            if (!data.Any())
            {
                return data;
            }

            string warehouseid = this.singleStoreService.CurrentStore;
            var ids = data.Select(x => x.Id).ToArray();

            var prices = await this.QueryGoodsPriceByIds(ids);
            //查询条件过滤门店仓库
            if (warehouseIdParam != string.Empty)
            {
                prices = prices.Where(x => x.warehouseID == warehouseIdParam).ToArray();
            }
            if (string.IsNullOrEmpty(warehouseid))
            {
                foreach (var m in data)
                {
                    m.GoodsPrices = prices.Where(x => x.goodsID == m.Id).ToArray();
                }
            }
            else
            {
                foreach (var m in data)
                {
                    m.GoodsPrices = prices.Where(x => x.goodsID == m.Id && x.warehouseID == warehouseid).ToArray();
                }
            }

            return data;
        }

        /// <summary>
        /// 关联商品进货单
        /// </summary>
        /// <param name="data"></param>
        /// <param name="warehouseIdParam"></param>
        /// <returns></returns>
        public async Task<GoodsInfo[]> AttachInOutWarehousing(GoodsInfo[] data, string warehouseIdParam = "")
        {
            if (!data.Any())
            {
                return data;
            }

            string warehouseid = this.singleStoreService.CurrentStore;
            var ids = data.Select(x => x.Id).ToArray();

            var db = await this.goodsInfos.GetDbContextAsync();
            var inOutWarehousings = await this.QueryInOutWarehousingsByIds(ids);
            //查询条件过滤门店仓库
            if (warehouseIdParam != string.Empty)
            {
                inOutWarehousings = inOutWarehousings.Where(x => x.warehouseID == warehouseIdParam).ToArray();
            }
            if (string.IsNullOrEmpty(warehouseid))
            {
                foreach (var m in data)
                {
                    m.InOutWarehousings = inOutWarehousings.Where(x => x.goodsID == m.Id).OrderByDescending(x => x.receiptDate).ToArray();
                    await db.AttachData<Supplier, InOutWarehousing>(m.InOutWarehousings, x => x.supplierID, (m, arr) =>
                    {
                        m.Supplier = arr.FirstOrDefault();
                    });
                }
            }
            else
            {
                foreach (var m in data)
                {
                    m.InOutWarehousings = inOutWarehousings.Where(x => x.goodsID == m.Id && x.warehouseID == warehouseid).OrderByDescending(x => x.receiptDate).ToArray();
                    await db.AttachData<Supplier, InOutWarehousing>(m.InOutWarehousings, x => x.supplierID, (m, arr) =>
                    {
                        m.Supplier = arr.FirstOrDefault();
                    });
                }
            }

            return data;
        }

        #region 关联商品分类 add by cl 20221112
        /// <summary>
        /// 关联商品分类
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<GoodsInfo[]> AttachGoodsCategory(GoodsInfo[] data)
        {
            var db = await this.goodsInfos.GetDbContextAsync();

            await db.AttachData<GoodsCategory, GoodsInfo>(data,
                idGetter: x => x.categoryID,
                action: (m, arr) => m.GoodsCategory = arr.FirstOrDefault());

            return data;
        }
        #endregion

        #region 综合报表添加额外数据 add by cl 20221122
        /// <summary>
        /// 综合报表添加额外数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<GoodsComprehensiveDto[]> AttachGoodsExtInfo(GoodsInfo[] data)
        {
            var todayDate = DateTime.Now;
            var goodsIds = data.Select(x => x.Id);
            var db = await this.goodsInfos.GetDbContextAsync();
            var inOutWarehousings = await db.Set<InOutWarehousing>().Where(x => goodsIds.Contains(x.goodsID) && x.inOrOut == (int)InOrOutEnum.IN).ToArrayAsync();
            //商品退货周期
            var gcReturnCycles = await db.Set<GoodsCategoryReturnCycle>().Where(x => x.IsDeleted == false).ToArrayAsync();
            //实时的销售
            var posSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID)).ToArrayAsync();
            //当天的销售
            var todayPosSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID) && x.operateTime.Year==todayDate.Year && x.operateTime.Month == todayDate.Month && x.operateTime.Day == todayDate.Day).ToArrayAsync();
            //会员价格
            var goodsMemberPrices = await db.Set<GoodsMemberPrice>().Where(x => goodsIds.Contains(x.goodsID)).ToArrayAsync();

            var goodsComprehensives = new List<GoodsComprehensiveDto>();
            foreach (var item in data)
            {
                //当天销售汇总（由于每天日结，因此为了计算实时库存，因此需要将库存扣掉当天销售）
                var todayPosSalesFlowsRet = todayPosSalesFlows.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID })
                    .Select(s => new
                    {
                        s.Key.goodsID,
                        s.Key.warehouseID,
                        saleQuantity = s.Sum(y => y.saleWay == SalesTypes.Refunds ? -y.saleQuantity : y.saleQuantity)
                    }).ToList();

                var goodsComprehensive = new GoodsComprehensiveDto
                {
                    goodsInfo = item
                };
                //第一次入库
                var firstInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID },
                    (key, group) => group.OrderBy(x => x.operateTime).FirstOrDefault()).ToList();
                foreach(var fio in firstInOutWarehousing)
                {
                    //获取当天的销售
                    var todaySaleQuantity = todayPosSalesFlowsRet?.FirstOrDefault(x => x.goodsID == fio.goodsID && x.warehouseID == fio.warehouseID)?.saleQuantity;
                    //去掉当天销售的历史库存
                    var hisGoodsNum = item.GoodsPrices?.FirstOrDefault(x => x.goodsID == fio.goodsID && x.warehouseID == fio.warehouseID)?.goodsNum;

                    //计算退货周期，即从首次入库时间计算到目前为止的天数，然后跟退货周期表进行对比
                    TimeSpan sp = DateTime.Now.Subtract((DateTime)fio.operateTime);
                    var dayInterval = sp.Days;
                    //获取到设置的退货天数，-99999为未设置
                    var remainPeriod = -99999;
                    var returnCycleDay = gcReturnCycles.FirstOrDefault(x => x.categoryId == item?.categoryID && x.supplierId == fio.supplierID)?.cycleDay;
                    if(returnCycleDay!=null)
                        remainPeriod = (int)returnCycleDay - dayInterval;
                    //remainPeriod = (int)(returnCycleDay == null ? 0 : returnCycleDay) - dayInterval;                    
                    //如果已经到期或超时，那返回-999999
                    if (remainPeriod < 0 && remainPeriod != -99999)
                        remainPeriod = -999999;

                    var gIndex = goodsComprehensive.GoodsExtInfos == null ? -1 : goodsComprehensive.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == fio.warehouseID);
                    if (gIndex < 0)
                    {
                        if (goodsComprehensive.GoodsExtInfos == null)
                        {
                            goodsComprehensive.GoodsExtInfos = new List<GoodsExtInfoDto>()
                            {
                                new GoodsExtInfoDto 
                                { 
                                    warehouseID = fio.warehouseID, 
                                    firstInQuantity = fio.quantity,
                                    replenishmentQuantity = 0, 
                                    saleQuantity = 0,
                                    warehouseGoodsNum = hisGoodsNum-(todaySaleQuantity == null ? 0 : todaySaleQuantity),
                                    remainPeriod = remainPeriod
                                }
                            };
                        }
                        else
                            goodsComprehensive.GoodsExtInfos.Add(new GoodsExtInfoDto 
                            { 
                                warehouseID = fio.warehouseID, 
                                firstInQuantity = fio.quantity, 
                                replenishmentQuantity = 0, 
                                saleQuantity = 0, 
                                warehouseGoodsNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity),
                                remainPeriod = remainPeriod
                            });
                    }
                    else
                    {
                        goodsComprehensive.GoodsExtInfos.ToList()[gIndex].firstInQuantity = fio.quantity;
                        goodsComprehensive.GoodsExtInfos.ToList()[gIndex].warehouseGoodsNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity);
                    }

                }
                //如果一次入库都没有做，那么实时库存就取历史库存-当天销售 add20240508
                if (!firstInOutWarehousing.Any())
                {
                    //通过获取商品价格里面的仓库Id来处理数据
                    foreach(var im in item.GoodsPrices)
                    {
                        //获取当天的销售
                        var todaySaleQuantity = todayPosSalesFlowsRet?.FirstOrDefault(x => x.goodsID == im.goodsID && x.warehouseID == im.warehouseID)?.saleQuantity;
                        //去掉当天销售的历史库存
                        var hisGoodsNum = item.GoodsPrices?.FirstOrDefault(x => x.goodsID == im.goodsID && x.warehouseID == im.warehouseID)?.goodsNum;

                        var gIndex = goodsComprehensive.GoodsExtInfos == null ? -1 : goodsComprehensive.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == im.warehouseID);
                        if (gIndex < 0)
                        {
                            if (goodsComprehensive.GoodsExtInfos == null)
                                goodsComprehensive.GoodsExtInfos = new List<GoodsExtInfoDto>() {
                                    new GoodsExtInfoDto { warehouseID = im.warehouseID, replenishmentQuantity = 0, warehouseGoodsNum = hisGoodsNum-(todaySaleQuantity == null ? 0 : todaySaleQuantity), firstInQuantity = 0, saleQuantity = 0 }
                                };
                            else
                                goodsComprehensive.GoodsExtInfos.Add(new GoodsExtInfoDto { warehouseID = im.warehouseID, replenishmentQuantity = 0, warehouseGoodsNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity), firstInQuantity = 0, saleQuantity = 0 });
                        }
                        else
                            goodsComprehensive.GoodsExtInfos.ToList()[gIndex].warehouseGoodsNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity);
                    }
                }
                //第一次之外的，即补货的
                var replenishmentInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID },
                    (key, group) => group.OrderBy(x => x.operateTime).Skip(1).GroupBy(m => new { m.goodsID, m.warehouseID })
                   .Select(s => new
                   {
                       s.Key.goodsID,
                       s.Key.warehouseID,
                       replenishmentQuantity = s.Sum(t => t.quantity)
                   }).FirstOrDefault()).ToList();
                foreach (var rio in replenishmentInOutWarehousing)
                {
                    //如果是null，表明只第一次入库，没有补货
                    if (rio == null)
                        continue;

                    var gIndex = goodsComprehensive.GoodsExtInfos == null ? -1 : goodsComprehensive.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == rio.warehouseID);
                    if (gIndex < 0)
                    {
                        if (goodsComprehensive.GoodsExtInfos == null)
                            goodsComprehensive.GoodsExtInfos = new List<GoodsExtInfoDto>() {
                            new GoodsExtInfoDto { warehouseID = rio.warehouseID, replenishmentQuantity = rio.replenishmentQuantity, firstInQuantity = 0, saleQuantity = 0 }
                        };
                        else
                            goodsComprehensive.GoodsExtInfos.Add(new GoodsExtInfoDto { warehouseID = rio.warehouseID, replenishmentQuantity = rio.replenishmentQuantity, firstInQuantity = 0, saleQuantity = 0 });
                    }
                    else
                        goodsComprehensive.GoodsExtInfos.ToList()[gIndex].replenishmentQuantity = rio.replenishmentQuantity;

                }

                //最近一次入库.获取到最近一次进货单价
                var latestInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID },
                    (key, group) => group.OrderByDescending(x => x.operateTime).FirstOrDefault()).ToList();
                foreach (var lio in latestInOutWarehousing)
                {
                    //获取对象是否存在
                    var gIndex = goodsComprehensive.GoodsExtInfos == null ? -1 : goodsComprehensive.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == lio.warehouseID);
                    if (gIndex < 0)
                    {
                        if (goodsComprehensive.GoodsExtInfos == null)
                            goodsComprehensive.GoodsExtInfos = new List<GoodsExtInfoDto>() {
                            new GoodsExtInfoDto { warehouseID = lio.warehouseID, latestInPrice=lio.price}
                        };
                        else
                            goodsComprehensive.GoodsExtInfos.Add(new GoodsExtInfoDto { warehouseID = lio.warehouseID, latestInPrice = lio.price });
                    }
                    else
                    {
                        goodsComprehensive.GoodsExtInfos.ToList()[gIndex].latestInPrice = lio.price;
                    }
                }

                //销售赋值
                var posSalesFlowsRet = posSalesFlows.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID })
                .Select(s => new
                {
                    s.Key.goodsID,
                    s.Key.warehouseID,
                    saleQuantity = s.Sum(y => y.saleWay == SalesTypes.Refunds ? -y.saleQuantity : y.saleQuantity)
                }).ToList();
                //遍历销售赋值
                foreach (var psf in posSalesFlowsRet)
                {
                    //获取对象是否存在
                    var gIndex = goodsComprehensive.GoodsExtInfos == null ? -1 : goodsComprehensive.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == psf.warehouseID);
                    if (gIndex < 0)
                    {
                        if (goodsComprehensive.GoodsExtInfos == null)
                            goodsComprehensive.GoodsExtInfos = new List<GoodsExtInfoDto>() {
                            new GoodsExtInfoDto { warehouseID = psf.warehouseID, replenishmentQuantity = 0, firstInQuantity = 0, saleQuantity = psf.saleQuantity}
                        };
                        else
                            goodsComprehensive.GoodsExtInfos.Add(new GoodsExtInfoDto { warehouseID = psf.warehouseID, replenishmentQuantity = 0, firstInQuantity = 0, saleQuantity = psf.saleQuantity });
                    }
                    else
                    {
                        goodsComprehensive.GoodsExtInfos.ToList()[gIndex].saleQuantity = psf.saleQuantity;
                    }
                }

                //会员价赋值
                var goodsMemberPricesRet = goodsMemberPrices.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID },
                    (key, group) => group.OrderByDescending(x => x.addTime).FirstOrDefault()).ToList();
                //遍历会员价赋值
                foreach (var gmp in goodsMemberPricesRet)
                {
                    //获取对象是否存在
                    var gIndex = goodsComprehensive.GoodsExtInfos == null ? -1 : goodsComprehensive.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == gmp.warehouseID);
                    if (gIndex < 0)
                    {
                        if (goodsComprehensive.GoodsExtInfos == null)
                            goodsComprehensive.GoodsExtInfos = new List<GoodsExtInfoDto>() {
                            new GoodsExtInfoDto { warehouseID = gmp.warehouseID, replenishmentQuantity = 0, firstInQuantity = 0, saleQuantity = 0, latestInPrice = 0, memberPrice = gmp.memberPrice}
                        };
                        else
                            goodsComprehensive.GoodsExtInfos.Add(new GoodsExtInfoDto { warehouseID = gmp.warehouseID, replenishmentQuantity = 0, firstInQuantity = 0, saleQuantity = 0, latestInPrice = 0, memberPrice = gmp.memberPrice });
                    }
                    else
                    {
                        goodsComprehensive.GoodsExtInfos.ToList()[gIndex].memberPrice = gmp.memberPrice;
                    }
                }

                //最终如果额外信息都没有，那么默认new一个实时库存为0的值
                if (goodsComprehensive.GoodsExtInfos == null)
                {
                    goodsComprehensive.GoodsExtInfos = new List<GoodsExtInfoDto>();
                    foreach (var gp in item.GoodsPrices)
                    {
                        goodsComprehensive.GoodsExtInfos.Add(new GoodsExtInfoDto { warehouseID = gp.warehouseID, replenishmentQuantity = 0, firstInQuantity = 0, saleQuantity = 0, warehouseGoodsNum = gp.goodsNum, remainPeriod = 0, latestInPrice = 0 });
                    }
                }

                goodsComprehensives.Add(goodsComprehensive);
            }

            return goodsComprehensives.ToArray();
        }
        #endregion

        #region 手机掌售通商品展示添加额外数据 add by cl 20231114
        /// <summary>
        /// 手机掌售通商品展示添加额外数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<GoodsMobileComprehensiveDto[]> AttachGoodsMobileExtInfo(GoodsInfo[] data)
        {
            var todayDate = DateTime.Now;
            var goodsIds = data.Select(x => x.Id);
            var db = await this.goodsInfos.GetDbContextAsync();
            var inOutWarehousings = await db.Set<InOutWarehousing>().Where(x => goodsIds.Contains(x.goodsID) && x.inOrOut == (int)InOrOutEnum.IN).ToArrayAsync();
            //实时的销售
            var posSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID)).ToArrayAsync();
            //当天的销售
            var todayPosSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID) && x.operateTime.Year == todayDate.Year && x.operateTime.Month == todayDate.Month && x.operateTime.Day == todayDate.Day).ToArrayAsync();
            var goodsMobileComprehensives = new List<GoodsMobileComprehensiveDto>();
            foreach (var item in data)
            {
                //当天销售汇总（由于每天日结，因此为了计算实时库存，因此需要将库存扣掉当天销售）
                var todayPosSalesFlowsRet = todayPosSalesFlows.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID })
                    .Select(s => new
                    {
                        s.Key.goodsID,
                        s.Key.warehouseID,
                        saleQuantity = s.Sum(y => y.saleWay == SalesTypes.Refunds ? -y.saleQuantity : y.saleQuantity)
                    }).ToList();

                var goodsMobileComprehensive = new GoodsMobileComprehensiveDto
                {
                    goodsInfo = item
                };
                //第一次入库
                var firstInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID },
                    (key, group) => group.OrderBy(x => x.operateTime).FirstOrDefault()).ToList();
                foreach (var fio in firstInOutWarehousing)
                {
                    //获取当天的销售
                    var todaySaleQuantity = todayPosSalesFlowsRet?.FirstOrDefault(x => x.goodsID == fio.goodsID && x.warehouseID == fio.warehouseID)?.saleQuantity;
                    //去掉当天销售的历史库存
                    var hisGoodsNum = item.GoodsPrices?.FirstOrDefault(x => x.goodsID == fio.goodsID && x.warehouseID == fio.warehouseID)?.goodsNum;

                    var gIndex = goodsMobileComprehensive.GoodsMobileExtInfos == null ? -1 : goodsMobileComprehensive.GoodsMobileExtInfos.ToList().FindIndex(x => x.warehouseID == fio.warehouseID);
                    if (gIndex < 0)
                    {
                        if (goodsMobileComprehensive.GoodsMobileExtInfos == null)
                        {
                            goodsMobileComprehensive.GoodsMobileExtInfos = new List<GoodsMobileExtInfoDto>()
                            {
                                new GoodsMobileExtInfoDto
                                {
                                    warehouseID = fio.warehouseID,
                                    warehouseGoodsNum = hisGoodsNum,
                                    warehouseGoodsRealNum = hisGoodsNum-(todaySaleQuantity == null ? 0 : todaySaleQuantity)
                                }
                            };
                        }
                        else
                            goodsMobileComprehensive.GoodsMobileExtInfos.Add(new GoodsMobileExtInfoDto
                            {
                                warehouseID = fio.warehouseID,
                                warehouseGoodsNum = hisGoodsNum,
                                warehouseGoodsRealNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity)
                            });
                    }
                    else
                    {
                        goodsMobileComprehensive.GoodsMobileExtInfos.ToList()[gIndex].warehouseGoodsNum = hisGoodsNum;
                        goodsMobileComprehensive.GoodsMobileExtInfos.ToList()[gIndex].warehouseGoodsRealNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity);
                    }
                }

                //最终如果额外信息都没有，那么默认new一个实时库存为0的值
                if (goodsMobileComprehensive.GoodsMobileExtInfos == null)
                {
                    goodsMobileComprehensive.GoodsMobileExtInfos = new List<GoodsMobileExtInfoDto>();
                    foreach (var gp in item.GoodsPrices)
                    {
                        goodsMobileComprehensive.GoodsMobileExtInfos.Add(new GoodsMobileExtInfoDto { warehouseID = gp.warehouseID, warehouseGoodsNum = gp.goodsNum, warehouseGoodsRealNum = gp.goodsNum });
                    }
                }

                //赋值供应商信息
                var suppliersDb = await db.Set<Supplier>().ToArrayAsync();
                var supplierInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.supplierID, x.goodsID },
                    (key, group) => group.OrderBy(x => x.operateTime).FirstOrDefault()).ToList();
                foreach (var sitem in supplierInOutWarehousing)
                {
                    var gIndex = goodsMobileComprehensive.Suppliers == null ? -1 : goodsMobileComprehensive.Suppliers.ToList().FindIndex(x => x.supplierID == sitem.supplierID);
                    if (gIndex < 0)
                    {
                        if (goodsMobileComprehensive.Suppliers == null)
                        {
                            goodsMobileComprehensive.Suppliers = new List<SupplierMobileInfoDto>()
                            {
                                new SupplierMobileInfoDto
                                {
                                    supplierID = sitem.supplierID,
                                    supplierName = suppliersDb.Where(x=>x.Id==sitem.supplierID).FirstOrDefault()?.supplierName,
                                    No = suppliersDb.Where(x=>x.Id==sitem.supplierID).FirstOrDefault()?.No
                                }
                            };
                        }
                        else
                            goodsMobileComprehensive.Suppliers.Add(new SupplierMobileInfoDto
                            {
                                supplierID = sitem.supplierID,
                                supplierName = suppliersDb.Where(x => x.Id == sitem.supplierID).FirstOrDefault()?.supplierName,
                                No = suppliersDb.Where(x => x.Id == sitem.supplierID).FirstOrDefault()?.No
                            });
                    }
                }
                //为null赋值空
                if (goodsMobileComprehensive.Suppliers == null)
                    goodsMobileComprehensive.Suppliers = new List<SupplierMobileInfoDto>();

                goodsMobileComprehensives.Add(goodsMobileComprehensive);
            }

            return goodsMobileComprehensives.ToArray();
        }
        /// <summary>
        /// 手机掌售通商品展示添加额外数据，根据商品Id获取的
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<GoodsMobileDetDto[]> AttachGoodsMobileExtInfoByIds(GoodsInfo[] data)
        {
            var todayDate = DateTime.Now;
            var goodsIds = data.Select(x => x.Id);
            var db = await this.goodsInfos.GetDbContextAsync();
            var inOutWarehousings = await db.Set<InOutWarehousing>().Where(x => goodsIds.Contains(x.goodsID) && x.inOrOut == (int)InOrOutEnum.IN).ToArrayAsync();
            //实时的销售
            var posSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID)).ToArrayAsync();
            //当天的销售
            var todayPosSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID) && x.operateTime.Year == todayDate.Year && x.operateTime.Month == todayDate.Month && x.operateTime.Day == todayDate.Day).ToArrayAsync();
            var goodsMobileDets = new List<GoodsMobileDetDto>();
            foreach (var item in data)
            {
                //当天销售汇总（由于每天日结，因此为了计算实时库存，因此需要将库存扣掉当天销售）
                var todayPosSalesFlowsRet = todayPosSalesFlows.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID })
                    .Select(s => new
                    {
                        s.Key.goodsID,
                        s.Key.warehouseID,
                        saleQuantity = s.Sum(y => y.saleWay == SalesTypes.Refunds ? -y.saleQuantity : y.saleQuantity)
                    }).ToList();

                var goodsMobileDet = new GoodsMobileDetDto
                {
                    goodsInfo = item
                };
                //第一次入库
                var firstInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID },
                    (key, group) => group.OrderBy(x => x.operateTime).FirstOrDefault()).ToList();
                foreach (var fio in firstInOutWarehousing)
                {
                    //获取当天的销售
                    var todaySaleQuantity = todayPosSalesFlowsRet?.FirstOrDefault(x => x.goodsID == fio.goodsID && x.warehouseID == fio.warehouseID)?.saleQuantity;
                    //去掉当天销售的历史库存
                    var hisGoodsNum = item.GoodsPrices?.FirstOrDefault(x => x.goodsID == fio.goodsID && x.warehouseID == fio.warehouseID)?.goodsNum;

                    var gIndex = goodsMobileDet.GoodsMobileExtInfos == null ? -1 : goodsMobileDet.GoodsMobileExtInfos.ToList().FindIndex(x => x.warehouseID == fio.warehouseID);
                    if (gIndex < 0)
                    {
                        if (goodsMobileDet.GoodsMobileExtInfos == null)
                        {
                            goodsMobileDet.GoodsMobileExtInfos = new List<GoodsMobileExtInfoDto>()
                            {
                                new GoodsMobileExtInfoDto
                                {
                                    warehouseID = fio.warehouseID,
                                    warehouseGoodsNum = hisGoodsNum,
                                    warehouseGoodsRealNum = hisGoodsNum-(todaySaleQuantity == null ? 0 : todaySaleQuantity)
                                }
                            };
                        }
                        else
                            goodsMobileDet.GoodsMobileExtInfos.Add(new GoodsMobileExtInfoDto
                            {
                                warehouseID = fio.warehouseID,
                                warehouseGoodsNum = hisGoodsNum,
                                warehouseGoodsRealNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity)
                            });
                    }
                    else
                    {
                        goodsMobileDet.GoodsMobileExtInfos.ToList()[gIndex].warehouseGoodsNum = hisGoodsNum;
                        goodsMobileDet.GoodsMobileExtInfos.ToList()[gIndex].warehouseGoodsRealNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity);
                    }
                }

                //最终如果额外信息都没有，那么默认new一个实时库存为0的值
                if (goodsMobileDet.GoodsMobileExtInfos == null)
                {
                    goodsMobileDet.GoodsMobileExtInfos = new List<GoodsMobileExtInfoDto>();
                    foreach (var gp in item.GoodsPrices)
                    {
                        goodsMobileDet.GoodsMobileExtInfos.Add(new GoodsMobileExtInfoDto { warehouseID = gp.warehouseID, warehouseGoodsNum = gp.goodsNum, warehouseGoodsRealNum = gp.goodsNum });
                    }
                }
                
                goodsMobileDets.Add(goodsMobileDet);
            }

            return goodsMobileDets.ToArray();
        }
        #endregion

        #region 手机掌售通商品综合查询添加额外数据 add by cl 20231214
        /// <summary>
        /// 手机掌售通商品综合查询添加额外数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<GoodsMobileComprehensiveDto[]> AttachGoodsMobileComprehensiveExtInfo(GoodsInfo[] data)
        {
            var todayDate = DateTime.Now;
            var goodsIds = data.Select(x => x.Id);
            var db = await this.goodsInfos.GetDbContextAsync();
            var inOutWarehousings = await db.Set<InOutWarehousing>().Where(x => goodsIds.Contains(x.goodsID) && x.inOrOut == (int)InOrOutEnum.IN).ToArrayAsync();
            //实时的销售
            var posSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID)).ToArrayAsync();
            //当天的销售
            var todayPosSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID) && x.operateTime.Year == todayDate.Year && x.operateTime.Month == todayDate.Month && x.operateTime.Day == todayDate.Day).ToArrayAsync();
            var goodsMobileComprehensives = new List<GoodsMobileComprehensiveDto>();
            foreach (var item in data)
            {
                //当天销售汇总（由于每天日结，因此为了计算实时库存，因此需要将库存扣掉当天销售）
                var todayPosSalesFlowsRet = todayPosSalesFlows.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID })
                    .Select(s => new
                    {
                        s.Key.goodsID,
                        s.Key.warehouseID,
                        saleQuantity = s.Sum(y => y.saleWay == SalesTypes.Refunds ? -y.saleQuantity : y.saleQuantity)
                    }).ToList();

                var goodsMobileComprehensive = new GoodsMobileComprehensiveDto
                {
                    goodsInfo = item
                };
                //第一次入库
                var firstInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID },
                    (key, group) => group.OrderBy(x => x.operateTime).FirstOrDefault()).ToList();
                foreach (var fio in firstInOutWarehousing)
                {
                    //获取当天的销售
                    var todaySaleQuantity = todayPosSalesFlowsRet?.FirstOrDefault(x => x.goodsID == fio.goodsID && x.warehouseID == fio.warehouseID)?.saleQuantity;
                    //去掉当天销售的历史库存
                    var hisGoodsNum = item.GoodsPrices?.FirstOrDefault(x => x.goodsID == fio.goodsID && x.warehouseID == fio.warehouseID)?.goodsNum;

                    var gIndex = goodsMobileComprehensive.GoodsMobileExtInfos == null ? -1 : goodsMobileComprehensive.GoodsMobileExtInfos.ToList().FindIndex(x => x.warehouseID == fio.warehouseID);
                    if (gIndex < 0)
                    {
                        if (goodsMobileComprehensive.GoodsMobileExtInfos == null)
                        {
                            goodsMobileComprehensive.GoodsMobileExtInfos = new List<GoodsMobileExtInfoDto>()
                            {
                                new GoodsMobileExtInfoDto
                                {
                                    warehouseID = fio.warehouseID,
                                    warehouseGoodsNum = hisGoodsNum,
                                    firstInQuantity = fio.quantity,
                                    replenishmentQuantity = 0,
                                    saleQuantity = 0,
                                    warehouseGoodsRealNum = hisGoodsNum-(todaySaleQuantity == null ? 0 : todaySaleQuantity)
                                }
                            };
                        }
                        else
                            goodsMobileComprehensive.GoodsMobileExtInfos.Add(new GoodsMobileExtInfoDto
                            {
                                warehouseID = fio.warehouseID,
                                warehouseGoodsNum = hisGoodsNum,
                                firstInQuantity = fio.quantity,
                                replenishmentQuantity = 0,
                                saleQuantity = 0,
                                warehouseGoodsRealNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity)
                            });
                    }
                    else
                    {
                        goodsMobileComprehensive.GoodsMobileExtInfos.ToList()[gIndex].firstInQuantity = fio.quantity;
                        goodsMobileComprehensive.GoodsMobileExtInfos.ToList()[gIndex].warehouseGoodsNum = hisGoodsNum;
                        goodsMobileComprehensive.GoodsMobileExtInfos.ToList()[gIndex].warehouseGoodsRealNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity);
                    }
                }

                //第一次之外的，即补货的
                var replenishmentInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID },
                    (key, group) => group.OrderBy(x => x.operateTime).Skip(1).GroupBy(m => new { m.goodsID, m.warehouseID })
                   .Select(s => new
                   {
                       s.Key.goodsID,
                       s.Key.warehouseID,
                       replenishmentQuantity = s.Sum(t => t.quantity)
                   }).FirstOrDefault()).ToList();
                foreach (var rio in replenishmentInOutWarehousing)
                {
                    //如果是null，表明只第一次入库，没有补货
                    if (rio == null)
                        continue;

                    var gIndex = goodsMobileComprehensive.GoodsMobileExtInfos == null ? -1 : goodsMobileComprehensive.GoodsMobileExtInfos.ToList().FindIndex(x => x.warehouseID == rio.warehouseID);
                    if (gIndex < 0)
                    {
                        if (goodsMobileComprehensive.GoodsMobileExtInfos == null)
                            goodsMobileComprehensive.GoodsMobileExtInfos = new List<GoodsMobileExtInfoDto>() {
                            new GoodsMobileExtInfoDto { warehouseID = rio.warehouseID, replenishmentQuantity = rio.replenishmentQuantity, firstInQuantity = 0, saleQuantity = 0 }
                        };
                        else
                            goodsMobileComprehensive.GoodsMobileExtInfos.Add(new GoodsMobileExtInfoDto { warehouseID = rio.warehouseID, replenishmentQuantity = rio.replenishmentQuantity, firstInQuantity = 0, saleQuantity = 0 });
                    }
                    else
                        goodsMobileComprehensive.GoodsMobileExtInfos.ToList()[gIndex].replenishmentQuantity = rio.replenishmentQuantity;

                }

                //销售赋值
                var posSalesFlowsRet = posSalesFlows.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.goodsID, x.warehouseID })
                    .Select(s => new
                    {
                        s.Key.goodsID,
                        s.Key.warehouseID,
                        saleQuantity = s.Sum(y => y.saleWay == SalesTypes.Refunds ? -y.saleQuantity : y.saleQuantity)
                    }).ToList();
                //遍历销售赋值
                foreach (var psf in posSalesFlowsRet)
                {
                    //获取对象是否存在
                    var gIndex = goodsMobileComprehensive.GoodsMobileExtInfos == null ? -1 : goodsMobileComprehensive.GoodsMobileExtInfos.ToList().FindIndex(x => x.warehouseID == psf.warehouseID);
                    if (gIndex < 0)
                    {
                        if (goodsMobileComprehensive.GoodsMobileExtInfos == null)
                            goodsMobileComprehensive.GoodsMobileExtInfos = new List<GoodsMobileExtInfoDto>() {
                            new GoodsMobileExtInfoDto { warehouseID = psf.warehouseID, replenishmentQuantity = 0, firstInQuantity = 0, saleQuantity = psf.saleQuantity}
                        };
                        else
                            goodsMobileComprehensive.GoodsMobileExtInfos.Add(new GoodsMobileExtInfoDto { warehouseID = psf.warehouseID, replenishmentQuantity = 0, firstInQuantity = 0, saleQuantity = psf.saleQuantity });
                    }
                    else
                    {
                        goodsMobileComprehensive.GoodsMobileExtInfos.ToList()[gIndex].saleQuantity = psf.saleQuantity;
                    }

                }

                //最终如果额外信息都没有，那么默认new一个实时库存为0的值
                if (goodsMobileComprehensive.GoodsMobileExtInfos == null)
                {
                    goodsMobileComprehensive.GoodsMobileExtInfos = new List<GoodsMobileExtInfoDto>();
                    foreach (var gp in item.GoodsPrices)
                    {
                        goodsMobileComprehensive.GoodsMobileExtInfos.Add(new GoodsMobileExtInfoDto { warehouseID = gp.warehouseID, replenishmentQuantity = 0, firstInQuantity = 0, saleQuantity = 0, warehouseGoodsNum = gp.goodsNum, warehouseGoodsRealNum = gp.goodsNum });
                    }
                }

                //赋值供应商信息
                var suppliersDb = await db.Set<Supplier>().ToArrayAsync();
                var supplierInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.Id).GroupBy(x => new { x.supplierID, x.goodsID },
                    (key, group) => group.OrderBy(x => x.operateTime).FirstOrDefault()).ToList();
                foreach (var sitem in supplierInOutWarehousing)
                {
                    var gIndex = goodsMobileComprehensive.Suppliers == null ? -1 : goodsMobileComprehensive.Suppliers.ToList().FindIndex(x => x.supplierID == sitem.supplierID);
                    if (gIndex < 0)
                    {
                        if (goodsMobileComprehensive.Suppliers == null)
                        {
                            goodsMobileComprehensive.Suppliers = new List<SupplierMobileInfoDto>()
                            {
                                new SupplierMobileInfoDto
                                {
                                    supplierID = sitem.supplierID,
                                    supplierName = suppliersDb.Where(x=>x.Id==sitem.supplierID).FirstOrDefault()?.supplierName,
                                    No = suppliersDb.Where(x=>x.Id==sitem.supplierID).FirstOrDefault()?.No
                                }
                            };
                        }
                        else
                            goodsMobileComprehensive.Suppliers.Add(new SupplierMobileInfoDto
                            {
                                supplierID = sitem.supplierID,
                                supplierName = suppliersDb.Where(x => x.Id == sitem.supplierID).FirstOrDefault()?.supplierName,
                                No = suppliersDb.Where(x => x.Id == sitem.supplierID).FirstOrDefault()?.No
                            });
                    }
                }
                //为null赋值空
                if (goodsMobileComprehensive.Suppliers == null)
                    goodsMobileComprehensive.Suppliers = new List<SupplierMobileInfoDto>();

                goodsMobileComprehensives.Add(goodsMobileComprehensive);
            }

            return goodsMobileComprehensives.ToArray();
        }
        #endregion

        #region 导出综合报表数据 add by cl 20240506
        /// <summary>
        /// 商品综合查询数据导出
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public async Task<Stream> ExportComprehensiveGoodsInfo(GoodsComprehensiveDto[] data)
        {
            if (data.Length > 0)
            {
                var db = await this.goodsInfos.GetDbContextAsync();
                var sysDics = await db.Set<SysDicsEntity>().ToArrayAsync();

                var stream = new MemoryStream();
                using (var excel = new ExcelPackage())
                {
                    //sheet名称
                    var defaultSheet = excel.Workbook.Worksheets.Add($"商品综合报表");
                    defaultSheet.Cells["A1:P1"].Merge = true;
                    defaultSheet.Cells["A1:P1"].Value = string.Concat("商品综合查询");
                    defaultSheet.Cells["A1:P1"].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                    defaultSheet.Cells["A1:P1"].Style.Font.Bold = true;
                    defaultSheet.Cells["A1:P1"].Style.Font.Size = 18;
                    defaultSheet.SetValue("A2", "供应商");
                    defaultSheet.SetValue("B2", "类别名称");
                    defaultSheet.SetValue("C2", "商品编号");
                    defaultSheet.SetValue("D2", "规格");
                    defaultSheet.SetValue("E2", "单位");
                    defaultSheet.SetValue("F2", "商品名称");
                    defaultSheet.SetValue("G2", "进货价");
                    defaultSheet.SetValue("H2", "最新入库价");
                    defaultSheet.SetValue("I2", "零售价");
                    defaultSheet.SetValue("J2", "会员价");
                    defaultSheet.SetValue("K2", "入库数量");
                    defaultSheet.SetValue("L2", "补货数量");
                    defaultSheet.SetValue("M2", "卖出数量");
                    defaultSheet.SetValue("N2", "库存");
                    defaultSheet.SetValue("O2", "实时库存");
                    defaultSheet.SetValue("P2", "剩余天数");
                    defaultSheet.Cells["A2:P2"].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                    defaultSheet.Cells["A2:P2"].Style.Font.Bold = true;
                    defaultSheet.Cells["A2:P2"].Style.Font.Size = 14;

                    for (int row = 3, i = 0; i < data.Length; i++)
                    {
                        var supplierName = string.Empty;
                        data[i].goodsInfo.GoodsPrices?.ForEach(e => supplierName += (e.Supplier?.supplierName + ","));
                        var costPrice = data[i].goodsInfo.GoodsPrices?.FirstOrDefault()?.costPrice ?? 0;
                        var memberPrice = data[i].goodsInfo.GoodsPrices?.FirstOrDefault()?.GoodsMemberPrice?.memberPrice ?? 0;
                        //最新入库价
                        var latestInPrice = data[i].GoodsExtInfos?.FirstOrDefault()?.latestInPrice ?? 0;
                        //单位转换
                        var unitCode = data[i].goodsInfo.unit;
                        var unitName = sysDics.FirstOrDefault(x => x.ID == unitCode)?.Title;
                        defaultSheet.SetValue(row + i, 1, supplierName.Trim(','));
                        defaultSheet.SetValue(row + i, 2, data[i].goodsInfo.GoodsCategory.categoryName);
                        defaultSheet.SetValue(row + i, 3, data[i].goodsInfo.No);
                        defaultSheet.SetValue(row + i, 4, data[i].goodsInfo.specifications);
                        defaultSheet.SetValue(row + i, 5, unitName);
                        defaultSheet.SetValue(row + i, 6, data[i].goodsInfo.goodsName);
                        defaultSheet.SetValue(row + i, 7, costPrice);
                        defaultSheet.SetValue(row + i, 8, latestInPrice);
                        defaultSheet.SetValue(row + i, 9, data[i].goodsInfo?.price??0);
                        defaultSheet.SetValue(row + i, 10, memberPrice);
                        defaultSheet.SetValue(row + i, 11, data[i].GoodsExtInfos.FirstOrDefault()?.firstInQuantity ?? 0);
                        defaultSheet.SetValue(row + i, 12, data[i].GoodsExtInfos.FirstOrDefault()?.replenishmentQuantity ?? 0);
                        defaultSheet.SetValue(row + i, 13, data[i].GoodsExtInfos.FirstOrDefault()?.saleQuantity ?? 0);
                        defaultSheet.SetValue(row + i, 14, data[i].goodsInfo.GoodsPrices?.FirstOrDefault()?.goodsNum ?? 0);
                        defaultSheet.SetValue(row + i, 15, data[i].GoodsExtInfos.FirstOrDefault()?.warehouseGoodsNum ?? 0);
                        defaultSheet.SetValue(row + i, 16, data[i].GoodsExtInfos.FirstOrDefault()?.remainPeriod ?? 0);

                        defaultSheet.Cells[row + i, 7].Style.Numberformat.Format = "#,##0.00";
                        defaultSheet.Cells[row + i, 8].Style.Numberformat.Format = "#,##0.00";
                        defaultSheet.Cells[row + i, 9].Style.Numberformat.Format = "#,##0.00";
                        defaultSheet.Cells[row + i, 10].Style.Numberformat.Format = "#,##0.00";
                        defaultSheet.Cells[row + i, 11].Style.Numberformat.Format = "#,##0.00";
                        defaultSheet.Cells[row + i, 12].Style.Numberformat.Format = "#,##0.00";
                        defaultSheet.Cells[row + i, 13].Style.Numberformat.Format = "#,##0.00";
                        defaultSheet.Cells[row + i, 14].Style.Numberformat.Format = "#,##0.00";
                        defaultSheet.Cells[row + i, 15].Style.Numberformat.Format = "#,##0.00";
                    }
                    defaultSheet.Cells[1, 1, data.Length + 3, 16].Style.Border.Top.Style = ExcelBorderStyle.Thin;
                    defaultSheet.Cells[1, 1, data.Length + 3, 16].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
                    defaultSheet.Cells[1, 1, data.Length + 3, 16].Style.Border.Left.Style = ExcelBorderStyle.Thin;
                    defaultSheet.Cells[1, 1, data.Length + 3, 16].Style.Border.Right.Style = ExcelBorderStyle.Thin;
                    defaultSheet.Cells[1, 1, data.Length + 3, 16].Style.Border.Top.Color.SetColor(System.Drawing.Color.Black);
                    defaultSheet.Cells[1, 1, data.Length + 3, 16].Style.Border.Bottom.Color.SetColor(System.Drawing.Color.Black);
                    defaultSheet.Cells[1, 1, data.Length + 3, 16].Style.Border.Left.Color.SetColor(System.Drawing.Color.Black);
                    defaultSheet.Cells[1, 1, data.Length + 3, 16].Style.Border.Right.Color.SetColor(System.Drawing.Color.Black);
                    //合计
                    defaultSheet.Cells[data.Length + 3, 1, data.Length + 3, 6].Merge = true;
                    defaultSheet.Cells[data.Length + 3, 1, data.Length + 3, 6].Value = "合计";
                    defaultSheet.Cells[data.Length + 3, 1, data.Length + 3, 6].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                    defaultSheet.Cells[data.Length + 3, 1, data.Length + 3, 6].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                    decimal sumCostPrice = 0.00M;
                    decimal sumLatestInPrice = 0.00M;
                    decimal sumPrice = 0.00M;
                    decimal sumMemberPrice = 0.00M;
                    decimal? sumFirstInQuantity = 0.00M;
                    decimal? sumReplenishmentQuantity = 0.00M;
                    decimal? sumSaleQuantity = 0.00M;
                    decimal? sumGoodsNum = 0.00M;
                    decimal? sumWarehouseGoodsNum = 0.00M;
                    foreach (var item in data)
                    {
                        sumCostPrice += item.goodsInfo.GoodsPrices?.FirstOrDefault()?.costPrice ?? 0;
                        sumLatestInPrice += item.GoodsExtInfos?.FirstOrDefault()?.latestInPrice ?? 0;
                        sumPrice += item.goodsInfo.price;
                        sumMemberPrice += item.goodsInfo.GoodsPrices?.FirstOrDefault()?.GoodsMemberPrice?.memberPrice ?? 0;
                        sumFirstInQuantity += item.GoodsExtInfos?.FirstOrDefault()?.firstInQuantity ?? 0;
                        sumReplenishmentQuantity += item.GoodsExtInfos?.FirstOrDefault()?.replenishmentQuantity ?? 0;
                        sumSaleQuantity += item.GoodsExtInfos?.FirstOrDefault()?.saleQuantity ?? 0;
                        sumGoodsNum += item.goodsInfo.GoodsPrices?.FirstOrDefault()?.goodsNum ?? 0;
                        sumWarehouseGoodsNum += item.GoodsExtInfos?.FirstOrDefault()?.warehouseGoodsNum ?? 0;
                    }
                    defaultSheet.Cells[data.Length + 3, 7, data.Length + 3, 7].Value = sumCostPrice;
                    defaultSheet.Cells[data.Length + 3, 8, data.Length + 3, 8].Value = sumLatestInPrice;
                    defaultSheet.Cells[data.Length + 3, 9, data.Length + 3, 9].Value = sumPrice;
                    defaultSheet.Cells[data.Length + 3, 10, data.Length + 3, 10].Value = sumMemberPrice;
                    defaultSheet.Cells[data.Length + 3, 11, data.Length + 3, 11].Value = sumFirstInQuantity;
                    defaultSheet.Cells[data.Length + 3, 12, data.Length + 3, 12].Value = sumReplenishmentQuantity;
                    defaultSheet.Cells[data.Length + 3, 13, data.Length + 3, 13].Value = sumSaleQuantity;
                    defaultSheet.Cells[data.Length + 3, 14, data.Length + 3, 14].Value = sumGoodsNum;
                    defaultSheet.Cells[data.Length + 3, 15, data.Length + 3, 15].Value = sumWarehouseGoodsNum;

                    defaultSheet.Cells.AutoFitColumns();
                    excel.SaveAs(stream);
                }

                stream.Position = 0;
                return stream;
            }
            return null;
        }
        #endregion

        #region 颜色尺码综合查询相关

        #region 颜色尺码综合报表查询
        /// <summary>
        /// 颜色尺码综合报表查询
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        public async Task<GoodsTsInfoDto[]> GetGoodsTsInfo(ProductPagingColorSizeRequestDto inputDto)
        {
            
            var db = await this.goodsInfos.GetDbContextAsync();
            var goodsData = db.Set<GoodsInfo>().Where(x => x.IsDeleted == false);
            goodsData = await FilterQueryAsync(db, goodsData, inputDto);
            var goodsResult = await goodsData?.ToArrayAsync();
            if (goodsResult?.Any() ?? false)
            {
                goodsResult = await AttachGoodsPrice(goodsResult);
                goodsResult = await AttachInOutWarehousing(goodsResult);
                goodsResult = await AttachGoodsCategory(goodsResult);

                var query = goodsResult.GroupBy(g => new { g.goodsName, g.colourCode, g.sizeStCode, g.categoryID, g.brand, g.saleType, g.metering, g.unit, g.qualityTime, g.price, g.goodsCode, g.goodsMstId })
                    .Select(g => new GoodsTsInfoDto
                    {
                        goodsName = g.Key.goodsName,
                        colourCode = g.Key.colourCode,
                        sizeStCode = g.Key.sizeStCode,
                        categoryID = g.Key.categoryID,
                        brand = g.Key.brand,
                        saleType = g.Key.saleType,
                        metering = g.Key.metering,
                        unit = g.Key.unit,
                        qualityTime = g.Key.qualityTime,
                        price = g.Key.price,
                        goodsCode = g.Key.goodsCode,
                        goodsMstId = g.Key.goodsMstId,
                        Id = g.Max(x => x.Id),
                        specifications = g.Max(x => x.specifications),
                        originPlace = g.Max(x => x.originPlace),
                        mnemonicWords = g.Max(x => x.mnemonicWords),
                        colourName = g.Max(x => x.colourName),
                        sizeStName = g.Max(x => x.sizeStName),
                        GoodsCategory = g.Max(x => x.GoodsCategory),
                        Sizes = g.Where(w=>w.goodsMstId == g.Key.goodsMstId).Select(x => new SizeInfoDto
                        {
                            goodsId = x.Id,
                            barCode = x.barCode,
                            No = x.No,
                            addUserID = x.addUserID,
                            addTime = x.addTime,
                            updateUserID = x.updateUserID,
                            updateTime = x.updateTime,
                            sizeCode = x.sizeCode,
                            sizeName = x.sizeName,
                            GoodsPrices = x.GoodsPrices.Where(a => a.goodsID == x.Id).ToList(),
                            InOutWarehousings = x.InOutWarehousings.Where(a => a.goodsID == x.Id).ToList(),
                            GoodsExtInfos = new List<GoodsExtInfoDto>() //此处一定要new
                        })?.ToList()
                    });
                var finRet = await AttachGoodsColorSizeExtInfoAsync(query.ToArray());
                finRet = finRet.OrderBy(o => o.goodsName).ToArray();
                return finRet;
            }
            return null;
        }
        #endregion

        #region 颜色尺码综合报表查询过滤
        private async Task<IQueryable<GoodsInfo>> FilterQueryAsync(DbContext db, IQueryable<GoodsInfo> query, ProductPagingColorSizeRequestDto dto)
        {
            await Task.CompletedTask;

            if (!string.IsNullOrWhiteSpace(dto.name))
            {
                query = query.Where(x => x.goodsName.Contains(dto.name));
            }

            if (!string.IsNullOrWhiteSpace(dto.goodsCode))
            {
                query = query.Where(x => x.goodsCode.Contains(dto.goodsCode));
            }

            if (!string.IsNullOrWhiteSpace(dto.warehouseId))
            {
                var goodIds = db.Set<WarehouseGoods>().Where(x => x.warehouseID == dto.warehouseId).Select(x => x.goodsID);
                query = query.Where(x => goodIds.Contains(x.Id));
            }

            //过滤是否有销售数据。不传为全部显示，"1"为当天有销售的，"2"为当天未销售过的，"3"为从未销售过的
            if (!string.IsNullOrWhiteSpace(dto.showType))
            {
                var currDate = DateTime.Now;
                var goodIds = db.Set<PosSalesFlow>().Where(x => x.operateTime.Year == currDate.Year && x.operateTime.Month == currDate.Month && x.operateTime.Day == currDate.Day).Select(x => x.goodsID);
                if (dto.showType == "1")
                    query = query.Where(x => goodIds.Contains(x.Id));
                else if (dto.showType == "2")
                    query = query.Where(x => !goodIds.Contains(x.Id));
                else if (dto.showType == "3")
                {
                    var goodIdAlls = db.Set<PosSalesFlow>().Select(x => x.goodsID);
                    query = query.Where(x => !goodIdAlls.Contains(x.Id));
                }
            }
            //过滤出n天内没有销售过的记录
            int beforeDays = dto.noSaleDays ?? 0;
            if (beforeDays > 0)
            {
                var currDate = DateTime.Now;
                var bDays = currDate.AddDays(-beforeDays);
                var goodIds = db.Set<PosSalesFlow>().Where(x => x.operateTime > bDays).Select(x => x.goodsID);
                query = query.Where(x => goodIds != null && !goodIds.Contains(x.Id));
            }

            //单店权限
            string roleWarehouseId = this.singleStoreService.CurrentStore;
            if (!string.IsNullOrWhiteSpace(roleWarehouseId))
            {
                var goodCategoryIds = db.Set<GoodsCategory>().Where(x => x.warehouseID == roleWarehouseId).Select(x => x.Id);
                query = query.Where(x => goodCategoryIds.Contains(x.categoryID));
            }

            //退货时过滤指定供应商的商品
            if (!string.IsNullOrWhiteSpace(dto.supplierID) && dto.InOrOut != 1)
            {
                var goodIds = db.Set<InOutWarehousing>().Where(x => x.supplierID == dto.supplierID).Select(x => x.goodsID);
                query = query.Where(x => goodIds.Contains(x.Id));
            }
            //退货时候将库存小于等于0的商品过滤掉
            if (dto.InOrOut == (int)InOrOutEnum.OUT)
            {
                var goodIds = db.Set<WarehouseGoods>().Where(x => x.goodsNum > 0).Select(x => x.goodsID);
                query = query.Where(x => goodIds.Contains(x.Id));
            }
            //根据条件是否显示库存小于等于0的商品
            if (dto.showZeroWarehouseGoodsNum)
            {
                var goodIds = db.Set<WarehouseGoods>().Where(x => x.goodsNum > 0).Select(x => x.goodsID);
                query = query.Where(x => goodIds.Contains(x.Id));
            }
            query = query.WhereIf(!string.IsNullOrWhiteSpace(dto.categoryID), x => x.categoryID == dto.categoryID);

            //添加采购查询日期条件 add20240612
            if (dto.beginDate != null && dto.endDate != null)
            {
                var goodIds = db.Set<InOutWarehousing>().WhereIf(dto.beginDate != null, x => x.receiptDate >= dto.beginDate.Value).WhereIf(dto.endDate != null, x => x.receiptDate <= dto.endDate.Value).Select(x => x.goodsID);
                query = query.Where(x => goodIds != null && goodIds.Contains(x.Id));
            }

            return query;
        }
        #endregion

        #region 综合报表添加额外数据
        /// <summary>
        /// 综合报表添加额外数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private async Task<GoodsTsInfoDto[]> AttachGoodsColorSizeExtInfoAsync(GoodsTsInfoDto[] data)
        {
            var todayDate = DateTime.Now;
            var goodsIds = data.SelectMany(x => x.Sizes).Select(y => y.goodsId);
            var db = await this.goodsInfos.GetDbContextAsync();
            var inOutWarehousings = await db.Set<InOutWarehousing>().Where(x => goodsIds.Contains(x.goodsID) && x.inOrOut == (int)InOrOutEnum.IN).ToArrayAsync();
            //商品退货周期
            var gcReturnCycles = await db.Set<GoodsCategoryReturnCycle>().Where(x => x.IsDeleted == false).ToArrayAsync();
            //实时的销售
            var posSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID)).ToArrayAsync();
            //当天的销售
            var todayPosSalesFlows = await db.Set<PosSalesFlow>().Where(x => goodsIds.Contains(x.goodsID) && x.operateTime.Year == todayDate.Year && x.operateTime.Month == todayDate.Month && x.operateTime.Day == todayDate.Day).ToArrayAsync();
            //会员价格
            var goodsMemberPrices = await db.Set<GoodsMemberPrice>().Where(x => goodsIds.Contains(x.goodsID)).ToArrayAsync();

            foreach (var goodsItem in data)
            {
                var categoryId = goodsItem.categoryID;
                foreach (var item in goodsItem.Sizes.ToList())
                {
                    //当天销售汇总（由于每天日结，因此为了计算实时库存，因此需要将库存扣掉当天销售）
                    var todayPosSalesFlowsRet = todayPosSalesFlows.Where(x => x.goodsID == item.goodsId).GroupBy(x => new { x.goodsID, x.warehouseID })
                        .Select(s => new
                        {
                            s.Key.goodsID,
                            s.Key.warehouseID,
                            saleQuantity = s.Sum(y => y.saleWay == SalesTypes.Refunds ? -y.saleQuantity : y.saleQuantity)
                        }).ToList();

                    //var goodsComprehensive = new GoodsComprehensiveDto
                    //{
                    //    goodsInfo = item
                    //};
                    //第一次入库
                    var firstInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.goodsId).GroupBy(x => new { x.goodsID, x.warehouseID },
                        (key, group) => group.OrderBy(x => x.operateTime).FirstOrDefault()).ToList();
                    foreach (var fio in firstInOutWarehousing)
                    {
                        //获取当天的销售
                        var todaySaleQuantity = todayPosSalesFlowsRet?.FirstOrDefault(x => x.goodsID == fio.goodsID && x.warehouseID == fio.warehouseID)?.saleQuantity;
                        //去掉当天销售的历史库存
                        var hisGoodsNum = item.GoodsPrices?.FirstOrDefault(x => x.goodsID == fio.goodsID && x.warehouseID == fio.warehouseID)?.goodsNum;

                        //计算退货周期，即从首次入库时间计算到目前为止的天数，然后跟退货周期表进行对比
                        TimeSpan sp = DateTime.Now.Subtract((DateTime)fio.operateTime);
                        var dayInterval = sp.Days;
                        //获取到设置的退货天数，-99999为未设置
                        var remainPeriod = -99999;
                        var returnCycleDay = gcReturnCycles.FirstOrDefault(x => x.categoryId == categoryId && x.supplierId == fio.supplierID)?.cycleDay;
                        if (returnCycleDay != null)
                            remainPeriod = (int)returnCycleDay - dayInterval;
                        //remainPeriod = (int)(returnCycleDay == null ? 0 : returnCycleDay) - dayInterval;                    
                        //如果已经到期或超时，那返回-999999
                        if (remainPeriod < 0 && remainPeriod != -99999)
                            remainPeriod = -999999;

                        var gIndex = item.GoodsExtInfos == null ? -1 : item.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == fio.warehouseID);
                        if (gIndex < 0)
                        {
                            //这边不为null，但长度为0，所以只要添加
                            item.GoodsExtInfos.Add(new GoodsExtInfoDto
                            {
                                warehouseID = fio.warehouseID,
                                firstInQuantity = fio.quantity,
                                replenishmentQuantity = 0,
                                saleQuantity = 0,
                                warehouseGoodsNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity),
                                remainPeriod = remainPeriod
                            });
                        }
                        else
                        {
                            item.GoodsExtInfos.ToList()[gIndex].firstInQuantity = fio.quantity;
                            item.GoodsExtInfos.ToList()[gIndex].warehouseGoodsNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity);
                        }

                    }
                    //如果一次入库都没有做，那么实时库存就取历史库存-当天销售 add20240508
                    if (!firstInOutWarehousing.Any())
                    {
                        //通过获取商品价格里面的仓库Id来处理数据
                        foreach (var im in item.GoodsPrices)
                        {
                            //获取当天的销售
                            var todaySaleQuantity = todayPosSalesFlowsRet?.FirstOrDefault(x => x.goodsID == im.goodsID && x.warehouseID == im.warehouseID)?.saleQuantity;
                            //去掉当天销售的历史库存
                            var hisGoodsNum = item.GoodsPrices?.FirstOrDefault(x => x.goodsID == im.goodsID && x.warehouseID == im.warehouseID)?.goodsNum;

                            var gIndex = item.GoodsExtInfos == null ? -1 : item.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == im.warehouseID);
                            if (gIndex < 0)
                            {
                                //这边不为null，但长度为0，所以只要添加
                                item.GoodsExtInfos.Add(new GoodsExtInfoDto { warehouseID = im.warehouseID, replenishmentQuantity = 0, warehouseGoodsNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity), firstInQuantity = 0, saleQuantity = 0 });
                            }
                            else
                                item.GoodsExtInfos.ToList()[gIndex].warehouseGoodsNum = hisGoodsNum - (todaySaleQuantity == null ? 0 : todaySaleQuantity);
                        }
                    }
                    //第一次之外的，即补货的
                    var replenishmentInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.goodsId).GroupBy(x => new { x.goodsID, x.warehouseID },
                        (key, group) => group.OrderBy(x => x.operateTime).Skip(1).GroupBy(m => new { m.goodsID, m.warehouseID })
                       .Select(s => new
                       {
                           s.Key.goodsID,
                           s.Key.warehouseID,
                           replenishmentQuantity = s.Sum(t => t.quantity)
                       }).FirstOrDefault()).ToList();
                    foreach (var rio in replenishmentInOutWarehousing)
                    {
                        //如果是null，表明只第一次入库，没有补货
                        if (rio == null)
                            continue;

                        var gIndex = item.GoodsExtInfos == null ? -1 : item.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == rio.warehouseID);
                        if (gIndex < 0)
                        {
                            //这边不为null，但长度为0，所以只要添加
                            item.GoodsExtInfos.Add(new GoodsExtInfoDto { warehouseID = rio.warehouseID, replenishmentQuantity = rio.replenishmentQuantity, firstInQuantity = 0, saleQuantity = 0 });
                        }
                        else
                            item.GoodsExtInfos.ToList()[gIndex].replenishmentQuantity = rio.replenishmentQuantity;

                    }

                    //最近一次入库.获取到最近一次进货单价
                    var latestInOutWarehousing = inOutWarehousings.Where(x => x.goodsID == item.goodsId).GroupBy(x => new { x.goodsID, x.warehouseID },
                        (key, group) => group.OrderByDescending(x => x.operateTime).FirstOrDefault()).ToList();
                    foreach (var lio in latestInOutWarehousing)
                    {
                        //获取对象是否存在
                        var gIndex = item.GoodsExtInfos == null ? -1 : item.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == lio.warehouseID);
                        if (gIndex < 0)
                        {
                            //这边不为null，但长度为0，所以只要添加
                            item.GoodsExtInfos.Add(new GoodsExtInfoDto { warehouseID = lio.warehouseID, latestInPrice = lio.price });
                        }
                        else
                        {
                            item.GoodsExtInfos.ToList()[gIndex].latestInPrice = lio.price;
                        }
                    }

                    //销售赋值
                    var posSalesFlowsRet = posSalesFlows.Where(x => x.goodsID == item.goodsId).GroupBy(x => new { x.goodsID, x.warehouseID })
                    .Select(s => new
                    {
                        s.Key.goodsID,
                        s.Key.warehouseID,
                        saleQuantity = s.Sum(y => y.saleWay == SalesTypes.Refunds ? -y.saleQuantity : y.saleQuantity)
                    }).ToList();
                    //遍历销售赋值
                    foreach (var psf in posSalesFlowsRet)
                    {
                        //获取对象是否存在
                        var gIndex = item.GoodsExtInfos == null ? -1 : item.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == psf.warehouseID);
                        if (gIndex < 0)
                        {
                            //这边不为null，但长度为0，所以只要添加
                            item.GoodsExtInfos.Add(new GoodsExtInfoDto { warehouseID = psf.warehouseID, replenishmentQuantity = 0, firstInQuantity = 0, saleQuantity = psf.saleQuantity });
                        }
                        else
                        {
                            item.GoodsExtInfos.ToList()[gIndex].saleQuantity = psf.saleQuantity;
                        }
                    }

                    //会员价赋值
                    var goodsMemberPricesRet = goodsMemberPrices.Where(x => x.goodsID == item.goodsId).GroupBy(x => new { x.goodsID, x.warehouseID },
                        (key, group) => group.OrderByDescending(x => x.addTime).FirstOrDefault()).ToList();
                    //遍历会员价赋值
                    foreach (var gmp in goodsMemberPricesRet)
                    {
                        //获取对象是否存在
                        var gIndex = item.GoodsExtInfos == null ? -1 : item.GoodsExtInfos.ToList().FindIndex(x => x.warehouseID == gmp.warehouseID);
                        if (gIndex < 0)
                        {
                            //这边不为null，但长度为0，所以只要添加
                            item.GoodsExtInfos.Add(new GoodsExtInfoDto { warehouseID = gmp.warehouseID, replenishmentQuantity = 0, firstInQuantity = 0, saleQuantity = 0, latestInPrice = 0, memberPrice = gmp.memberPrice });
                        }
                        else
                        {
                            item.GoodsExtInfos.ToList()[gIndex].memberPrice = gmp.memberPrice;
                        }
                    }
                }
            }
            return data.ToArray();
        }
        #endregion

        #endregion

        #region 更新是否新品的状态
        public async Task UpdateIsNewProductStatus(UpdateGoodsIsNewProductStatusDto[] dto)
        {
            dto.Should().NotBeNullOrEmpty();

            var db = await this.goodsInfos.GetDbContextAsync();
            var set = db.Set<GoodsInfo>();
            foreach (var m in dto)
            {
                var goods = await set.FirstOrDefaultAsync(x => x.Id == m.goodsId);
                if (goods == null)
                {
                    continue;
                }

                if (m.isNewProduct != null)
                {
                    goods.isNewProduct = m.isNewProduct.Value;
                    goods.updateTime = DateTime.Now;
                }

                this.entityHelper.SetUpdationInfo(goods);
            }

            await db.SaveChangesAsync();
        }
        #endregion

        #region 下拉列表查询商品，通过查询语句
        /// <summary>
        /// 下拉列表查询商品，通过查询语句
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<IEnumerable<QueryAllGoodsByWarehouseResponse>> QueryAllGoodsByWarehouseBySql(QueryAllGoodsByWarehouseInputDto dto)
        {
            //单店权限
            string roleWarehouseId = this.singleStoreService.CurrentStore;
            var strSql = @"SELECT gi.id goodsID, gi.barCode, gi.No, gi.goodsName
                             FROM goods_info gi
                           LEFT JOIN warehouse_goods wg ON gi.id = wg.goodsID
						    WHERE 1=1";
            if (!string.IsNullOrWhiteSpace(dto.warehouseId))
                strSql = strSql + $@"         AND wg.warehouseID = '{dto.warehouseId}'";

            if (!string.IsNullOrWhiteSpace(roleWarehouseId))
                strSql = strSql + $@"         AND wg.warehouseID = '{roleWarehouseId}'";

            var resultRes = await _dapperRepository.GetListAsync<QueryAllGoodsByWarehouseResponse>(strSql);

            var count = resultRes.Count();

            return resultRes;
        }
        #endregion
    }
}
